package com.cash.app.net

import com.cash.app.BuildConfig
import com.cash.app.constant.AppConstant
import com.cash.app.constant.AppConstant.NET_TIMEOUT
import com.cash.app.net.NetConstant.HV_CONTENT_TYPE
import com.cash.app.net.NetConstant.H_CONTENT_TYPE
import okhttp3.Cache
import okhttp3.OkHttpClient
import okhttp3.internal.http2.Header
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit

object RetrofitClient {
    private var retrofit: Retrofit? = null
    private var okHttpClient: OkHttpClient? = null

    fun init(
        connectTimeout: Long = NET_TIMEOUT,
        readTimeout: Long = NET_TIMEOUT,
        writeTimeout: Long = NET_TIMEOUT,
        cache: Cache? = null,
    ) {
        okHttpClient = OkHttpClient.Builder().apply {
            Header(H_CONTENT_TYPE, HV_CONTENT_TYPE)
            connectTimeout(connectTimeout, TimeUnit.SECONDS)
            readTimeout(readTimeout, TimeUnit.SECONDS)
            writeTimeout(writeTimeout, TimeUnit.SECONDS)

            if (BuildConfig.DEBUG) {
                addInterceptor(HttpLoggingInterceptor().apply {
                    level = HttpLoggingInterceptor.Level.BODY
                })
            } else {
                addInterceptor(HttpLoggingInterceptor().apply {
                    level = HttpLoggingInterceptor.Level.BASIC
                })
            }

            addInterceptor(BaseBodyInterceptor())
            addInterceptor(RetryChangeDomainInterceptor())

            cache?.let { cache(it) }
        }.build()

        val baseUrl = if (BuildConfig.DEBUG) {
            AppConstant.API_HOST_D
        } else {
            AppConstant.API_HOST_R
        }
        updateRetrofit(baseUrl)
    }

    private fun updateRetrofit(baseUrl: String) {
        if (okHttpClient == null) {
            throw IllegalStateException("RetrofitClient must be initialized first")
        }
        retrofit = Retrofit.Builder().baseUrl(baseUrl).client(okHttpClient!!)
            .addConverterFactory(GsonConverterFactory.create()).build()
    }

    /**
     * Update base URL for all subsequent network requests
     * This change will be effective until app restart
     */
    fun updateBaseUrl(newBaseUrl: String) {
        updateRetrofit(newBaseUrl)
    }

    fun <T> createService(serviceClass: Class<T>): T {
        if (retrofit == null) {
            throw IllegalStateException("RetrofitClient must be initialized first")
        }
        return retrofit!!.create(serviceClass)
    }

    fun <T> createService(
        serviceClass: Class<T>, baseUrl: String, client: OkHttpClient? = null
    ): T {
        return Retrofit.Builder().baseUrl(baseUrl).client(client ?: okHttpClient!!)
            .addConverterFactory(GsonConverterFactory.create()).build().create(serviceClass)
    }
}